<!--
 * @Author       : wfl
 * @LastEditors: ww
 * @description  :
 * @updateInfo   :
 * @Date         : 2022-11-23 16:28:21
 * @LastEditTime: 2023-06-30 17:40:52
-->
<script lang="ts" setup name="ConditionNode">
import ActionType from '@main/views/approve-workflow/WorkFlow/ActionType.vue'
import ellipsis from '@main/views/approve-workflow/WorkFlow/Ellipsis.vue'
import { ElTooltip } from 'element-plus'
import { computed, reactive } from 'vue'
import { ComparatorMap, EComparatorType, ECompare } from '@main/views/approve-workflow/enum'
import { groupNames, ValueType } from '../params'

const props = defineProps({
  config: {
    type: Object,
    default: () => {
      return {}
    }
  },
  conditionOrder: {
    type: Number,
    default: 1
  },
  // 条件数
  size: {
    type: Number,
    default: 0
  }
})

const emits = defineEmits([
  'selected',
  'leftMove',
  'copy',
  'delNode',
  'rightMove',
  'insertNode'
])

const state = reactive({
  ValueType,
  groupNames,
  placeholder: '请设置条件',
  errorInfo: '',
  showError: false
})

const isDefaultBranch = computed(() => props.config.name === '系统默认条件')
const content = computed(() => {
  const groups = props.config.props.groups
  const confitions: string[] = []
  groups.forEach(
    (group: {
      conditions: { valueType: any; title: any; value: any[]; }[]
      comparator: string
    }) => {
      const subConditions: string[] = []
      group.conditions.forEach(
        (subCondition: { valueType: any; title: any; value: any[]; }) => {
          let subConditionStr = ''
          switch (subCondition.valueType) {
            case ValueType.dept:
            case ValueType.user:
              subConditionStr = `${subCondition.title}属于[ ${String(
                subCondition.value.map(u => u.elementName)
              ).replaceAll(',', '、')} ]之一`
              break
            case ValueType.number:
            case ValueType.string:
              subConditionStr = getOrdinaryConditionContent(subCondition)
              break
            case ValueType.date:
            case ValueType.time:
              subConditionStr = getOrdinaryConditionContent(subCondition)
              break
          }
          subConditions.push(subConditionStr)
        }
      )
      // 根据子条件关系构建描述
      const subConditionsStr = String(subConditions).replaceAll(
        ',',
        subConditions.length > 1
          ? group.comparator === 'AND'
            ? ') 且 ('
            : ') 或 ('
          : group.comparator === 'AND'
            ? ' 且 '
            : ' 或 '
      )
      confitions.push(
        subConditions.length > 1 ? `(${subConditionsStr})` : subConditionsStr
      )
    }
  )
  // 构建最终描述
  return String(confitions).replaceAll(
    ',',
    props.config.props.groupsType === 'AND' ? ' 且 ' : ' 或 '
  )
})
const isEmpty = computed(() => (content.value || '').trim() === '')

const getDefault = (val: string, df: any) => {
  return (val && val !== '') ? val : df
}
const getOrdinaryConditionContent = (subCondition: {
  valueType?: any
  title: any
  value: any
  compare?: any
}) => {
  switch (subCondition.compare) {
    case EComparatorType.完全包含:
      return `${subCondition.title}为[${String(subCondition.value).replaceAll(
        ',',
        '、'
      )}]中之一`
    case ECompare.B:
      return `${subCondition.value[0]} < ${subCondition.title} < ${subCondition.value[1]}`
    case ECompare.AB:
      return `${subCondition.value[0]} ≤ ${subCondition.title} < ${subCondition.value[1]}`
    case ECompare.BA:
      return `${subCondition.value[0]} < ${subCondition.title} ≤ ${subCondition.value[1]}`
    case ECompare.ABA:
      return `${subCondition.value[0]} ≤ ${subCondition.title} ≤ ${subCondition.value[1]}`
    case EComparatorType.小于等于:
      return `${subCondition.title} ≤ ${getDefault(
        subCondition.value[0],
        ' ?'
      )}`
    case EComparatorType.大于等于:
      return `${subCondition.title} ≥ ${getDefault(
        subCondition.value[0],
        ' ?'
      )}`
    default:
      return `${subCondition.title}${
        (ComparatorMap as any)[subCondition.compare]
      }${getDefault(subCondition.value[0], ' ?')}`
  }
}
// 校验数据配置的合法性
const validate = (err: string[]) => {
  const _props = props.config.props
  const isSystemGonfig = props.config.name === '系统默认条件'
  if (isSystemGonfig)
    return true
  if (_props.groups.length <= 0) {
    state.showError = true
    state.errorInfo = '请设置分支条件'
    err.push(`${_props.config.name} 未设置条件`)
  }
  else {
    for (let i = 0; i < _props.groups.length; i++) {
      if (_props.groups[i].cids.length === 0) {
        state.showError = true
        state.errorInfo = `请设置条件组${groupNames[i]}内的条件`
        err.push(`条件 ${props.config.name} 条件组${groupNames[i]}内未设置条件`)
        break
      }
      else {
        const conditions = _props.groups[i].conditions
        for (let ci = 0; ci < conditions.length; ci++) {
          const subc = conditions[ci]
          if (subc.value.length === 0)
            state.showError = true
          else
            state.showError = false

          if (state.showError) {
            state.errorInfo = `请完善条件组${groupNames[i]}内的${subc.title}条件`
            err.push(
              `条件 ${props.config.name} 条件组${groupNames[i]}内${subc.title}条件未完善`
            )
            return false
          }
        }
      }
    }
  }
  return !state.showError
}

defineExpose({ validate })

const emitArr = [
  'selected',
  'leftMove',
  'copy',
  'delNode',
  'rightMove',
  'insertNode'
] as const
type TEmit = (typeof emitArr)[number]
const handSelected = (type: TEmit, val?: string) => {
  // 系统默认条件不可配置
  if (type === 'selected' && isDefaultBranch.value)
    return
  emits(type, val)
}
</script>

<template>
  <div class="node" :class="{ 'node-error-state': state.showError }">
    <div class="node-body" :class="{ error: state.showError }">
      <div
        v-if="conditionOrder > 1"
        class="node-body-left"
        @click="handSelected('leftMove')"
      >
        <i class="el-icon-arrow-left"></i>
      </div>
      <div class="node-body-main" @click="handSelected('selected')">
        <div class="node-body-main-header">
          <i class="ikflow ikflow-24gf-branches node-icon"></i>
          <ellipsis
            class="title"
            hover-tip
            :content="config.name ? config.name : `条件${conditionOrder}`"
          />
          <template v-if="!isDefaultBranch">
            <span class="level">优先级{{ config.conditionOrder }}</span>
            <span class="option">
              <ElTooltip effect="dark" content="复制条件" placement="top">
                <i class="ikflow ikflow-fuzhi" @click.stop="handSelected('copy')"></i>
              </ElTooltip>
              <ElTooltip effect="dark" content="删除条件" placement="top">
                <i
                  class="ikflow ikflow-guanbi trans-all-25"
                  @click.stop="handSelected('delNode')"
                ></i>
              </ElTooltip>
            </span>
          </template>
        </div>
        <div class="node-body-main-content">
          <template v-if="!isDefaultBranch">
            <span v-if="isEmpty" class="placeholder">{{
              state.placeholder
            }}</span>
            <ellipsis
              v-else
              hover-tip
              :row="4"
              :content="content"
            />
          </template>
          <template v-else> 系统默认条件 </template>
        </div>
      </div>
      <div
        v-if="conditionOrder < size"
        class="node-body-right"
        @click="handSelected('rightMove')"
      >
        <i class="el-icon-arrow-right"></i>
      </div>
      <div v-if="state.showError" class="node-error">
        <ElTooltip
          effect="dark"
          :content="state.errorInfo"
          placement="top-start"
        >
          <i class="el-icon-warning-outline"></i>
        </ElTooltip>
      </div>
    </div>
    <div class="node-footer">
      <div class="btn">
        <ActionType @insertNode="(type) => handSelected('insertNode', type)" />
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.node-error-state {
  .node-body {
    box-shadow: 0 0 5px 0 #f56c6c !important;
  }
}

.node {
  padding: 30px 55px 0;
  width: var(--node-width);

  .node-body {
    cursor: pointer;
    min-height: 80px;
    max-height: 120px;
    position: relative;
    border-radius: 5px;
    background-color: var(--el-bg-color);
    box-shadow: var(--el-box-shadow-light);

    &:hover {
      .node-body-left,
      .node-body-right {
        i {
          display: block !important;
        }
      }

      .node-body-main {
        .level {
          display: none !important;
        }

        .option {
          display: inline-block !important;
        }
      }

      box-shadow: 0 0 3px 0 var(--theme-primary);
    }

    .node-body-left,
    .node-body-right {
      display: flex;
      align-items: center;
      position: absolute;
      height: 100%;

      i {
        display: none;
      }

      &:hover {
        background-color: #ececec;
      }
    }

    .node-body-left {
      left: 0;
    }

    .node-body-right {
      right: 0;
      top: 0;
    }

    .node-body-main {
      width: 100%;
      display: inline-block;

      .node-body-main-header {
        border-top-left-radius: 5px;
        border-top-right-radius: 5px;
        padding: 8px 15px;
        font-size: xx-small;
        position: relative;
        background-color: rgb(54 194 194);
        display: flex;
        align-items: center;

        .title {
          color: #fff;
          display: inline-block;
          width: 125px;
        }

        .level {
          position: absolute;
          right: 15px;
          color: #fff;
        }

        .option {
          position: absolute;
          right: 6px;
          top: 5px;
          color: #fff;
          display: none;
          font-size: medium;
          transition: all 0.25s ease-in-out;

          i {
            padding: 0 3px;
          }
        }
      }

      .node-body-main-content {
        padding: 6px;
        color: var(--ik-pagin-text-color);
        font-size: 14px;

        i {
          position: absolute;
          top: 55%;
          right: 10px;
          font-size: medium;
        }

        .placeholder {
          color: var(--ik-pagin-text-color);
        }
      }
    }

    .node-error {
      position: absolute;
      right: -40px;
      top: 20px;
      font-size: 25px;
      color: #f56c6c;
    }
  }

  .node-footer {
    position: relative;

    .btn {
      width: 100%;
      display: flex;
      padding: 32px 0;
      justify-content: center;
    }

    :deep(.el-button) {
      height: 32px;
      width: 32px;
    }

    &::before {
      content: '';
      position: absolute;
      inset: 0;
      z-index: -1;
      margin: auto;
      width: 2px;
      height: 100%;
      background-color: var(--el-text-color-disabled);
    }
  }
}
</style>
